<?php

namespace App\Repositories\Manage;

use App\Models\Menu;

class MenuRepository
{
    public function getMenus($filter = null)
    {
        $res = Menu::query()
            ->when(!empty($filter['keywords']), function ($query) use ($filter) {
                return $query->where("name", "like", "%{$filter['keywords']}%");
            })
            ->where('id', '>', 0)
            ->orderBy("sort", "asc")
            ->orderBy("id", "asc")
            ->get()
            ->toArray();

        if (empty($filter['keywords']))
            $res = list_to_tree($res, 'id', "pid", "children");

        return $res;
    }

    /**
     * 获取类型
     */
    public function getOptions()
    {
        $res = Menu::query()->where('id', '>', 0)
            ->orderBy("sort", 'asc')
            ->get(['id as value', 'name as label', 'pid'])
            ->toArray();

        $res = list_to_tree($res, 'value', "pid", "children");

        return $res;
    }

    public function getOne($id = null)
    {
        return Menu::query()->where(['id' => $id])->first();
    }

    public function saveOrUpdate($data = [], $id = 0)
    {
        if (!empty($data['id']))
            unset($data['id']);

        if (!empty($data['s']))
            unset($data['s']);

        if ($data['keepAlive']) {
            $data['keepAlive'] = 1;
        }

        if (intval($id)) {
            Menu::where("id", $id)->update($data);
            return $id;
        } else {
            $res = Menu::create($data);

            return $res['id'] ?? "";
        }
    }

    /**
     * 批量删除
     * @param null $ids
     */
    public function batchDelete($ids = null)
    {

        if (intval($ids)) {
            Menu::where(['id' => $ids])->delete();
        } else {
            Menu::whereIn("id", $ids)->delete();
        }

        return retSuc([], "删除成功");
    }

    /**
     * 删除菜单缓存
     * @param null $uid
     */
    public function delMenuReids($uid = null)
    {
        $roleIds = (new UserRepository())->getRolesById($uid);
        $this->getMenuByRoleId($roleIds, ["MENU", "CATALOG"], $uid);
        return true;
    }

    public function getMenuByRoleId($roleId = null, $type = null, $uid = null)
    {
        if (empty($roleId))
            return [];

        $redis_key = "menusList_" . $uid;
        $res = getRedisByKey($redis_key, 2);
        if ($uid != 88) {
            if (!empty($res))
                return $res;
        }

        $fields = "menu.id,menu.type,menu.name,menu.path,menu.component,menu.perm,menu.redirect,menu.visible,menu.icon,menu.alwaysShow,menu.keepAlive,menu.pid,";

        $res = Menu::query()
            ->when(!empty($roleId), function ($query) use ($roleId) {
                if (is_array($roleId)) {
                    $query->whereIn("rm.role_id", $roleId);
                }
            })
            ->when(!empty($type), function ($query) use ($type) {
                if (is_array($type)) {
                    $query->whereIn("menu.type", $type);
                } else {
                    $query->where("menu.type", $type);
                }
            })
            ->join("role_menu as rm", "rm.menu_id", "=", "menu.id")
            ->whereNull("rm.deleted_at")
            ->where("menu.visible", 1)
            ->orderBy("menu.sort", "asc")
            ->orderBy("menu.id", "asc")
            ->get(array_filter(explode(",", $fields)));

        if (empty($res))
            return [];

        $menus = $this->_format_menu($res->toArray());
        $res = list_to_tree($menus, 'id', "pid", "children");

        foreach ($res as $k => &$v) {
            unset($v['id']);
            unset($v['pid']);

            foreach ($v['children'] as $sk => &$sv) {
                unset($sv['id']);
                unset($sv['pid']);
            }
        }

        setRedisByDb($redis_key, $res, null, 2);

        return $res;
    }

    /**
     * 格式化菜单
     * @param array $menus
     * @return array
     */
    private function _format_menu($menus = [])
    {
        if (empty($menus))
            return [];

        $data = [];
        foreach ($menus as $k => $v) {
            $d = [
                "id" => $v['id'],
                "pid" => $v['pid'],
                "name" => $v['pid'] == 0 ? $v['path'] : $v['name'],
                "path" => $v['path'],
                "redirect" => $v['redirect'],
                "component" => $v['component'],
                'perm' => $v['perm'] ?? "",
                "meta" => [
                    'hidden' => false,
                    'icon' => $v['icon'] ?? "",
                    'title' => $v['name'],
                    'roles' => $this->getRoleNameByMenuId($v['id']),
                ],
            ];

            if ($v['pid']) {
                $d['meta']['keepAlive'] = $v['keepAlive'];
            }

            $data[] = $d;
        }

        return $data;
    }

    /**
     * 用户对应的->权限
     * @param null $user_id
     */
    public function getPermByUserId($user_id = null)
    {
        if (!intval($user_id))
            return null;

        $roleIds = (new UserRepository())->getRolesById($user_id);
        if (empty($roleIds))
            return null;

        return (new Menu())->setTable("m")
            ->from("menu as m")
            ->join("role_menu as rm", 'rm.menu_id', "=", "m.id")
            ->where("m.visible", 1)
            ->where("m.type", "=", "BUTTON")
            ->whereIn("rm.role_id", $roleIds)
            ->whereNull("rm.deleted_at")
            ->pluck("m.perm")
            ->toArray();
    }

    /**
     * 菜单对应的->角色
     * @param null $menu_id
     */
    public function getRoleNameByMenuId($menu_id = null)
    {
        if (!intval($menu_id))
            return null;

        return (new Menu())->setTable("m")
            ->from("menu as m")
            ->join("role_menu as rm", 'rm.menu_id', "=", "m.id")
            ->join("role as r", 'r.id', "=", "rm.role_id")
            ->where("m.id", $menu_id)
            ->whereNull("rm.deleted_at")
            ->pluck("r.code")
            ->toArray();

    }
}
